﻿using IWshRuntimeLibrary;
using Microsoft.Win32;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using System.Runtime.InteropServices;

namespace BingWallpaper
{
    public class Para
    {
        public string SavePath { get; set; }
        public bool IsBak { get; set; }
        public bool IsReplace { get; set; }
        public string Timing { get; set; }
    }
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Para para;
        WindowState ws;
        WindowState wsl;
        NotifyIcon notifyIcon;
        DispatcherTimer dispatcherTimer = new DispatcherTimer();
        string exeName = "BingWallpaper";
        string configPath = GetProjectRootPath() + "\\Config.txt";

        public MainWindow()
        {
            InitializeComponent();
            ReadConfig();
            TaskIcon();
            //保证窗体显示在上方。
            wsl = WindowState;
            if (!Directory.Exists(GetProjectRootPath() + "\\temp\\"))
            {
                Directory.CreateDirectory(GetProjectRootPath() + "\\temp\\");
            }
            ClearTemp();
            if (IsExistStart())
            {
                this.btnAutoStart.Content = "关闭开机启动";
                Start();
            }
            else
                this.btnAutoStart.Content = "开机启动";

        }
        /// <summary>
        /// 清除临时文件
        /// </summary>
        private void ClearTemp()
        {
            DirectoryInfo folder = new DirectoryInfo(GetProjectRootPath() + "\\temp\\");
            foreach (FileInfo file in folder.GetFiles("*.jpg"))
            {
                if (file.Name != "debug.jpg")
                    System.IO.File.Delete(file.FullName);
            }

        }
        /// <summary>
        /// 任务栏图标
        /// </summary>
        private void TaskIcon()
        {
            this.notifyIcon = new NotifyIcon();
            this.notifyIcon.BalloonTipText = "Hello, BingWallpaper"; //设置程序启动时显示的文本
            this.notifyIcon.Text = "BingWallpaper";//最小化到托盘时，鼠标点击时显示的文本
            this.notifyIcon.Icon = new System.Drawing.Icon("wallpaper.ico");//程序图标
            this.notifyIcon.Visible = true;
            this.notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu();
            this.notifyIcon.ContextMenu.MenuItems.Add("Open");
            this.notifyIcon.ContextMenu.MenuItems[0].Click += MainWindow_OpenClick;
            this.notifyIcon.ContextMenu.MenuItems.Add("Exit");
            this.notifyIcon.ContextMenu.MenuItems[1].Click += MainWindow_ExitClick;
            notifyIcon.MouseDoubleClick += OnNotifyIconDoubleClick;
            this.notifyIcon.ShowBalloonTip(1000);
        }

        private void MainWindow_ExitClick(object sender, EventArgs e)
        {
            ExitApp();
        }

        private void MainWindow_OpenClick(object sender, EventArgs e)
        {
            this.Show();
            WindowState = wsl;
        }

        private void OnNotifyIconDoubleClick(object sender, EventArgs e)
        {
            this.Show();
            WindowState = wsl;
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.Hide();
            e.Cancel = true;
        }

        private void Window_StateChanged(object sender, EventArgs e)
        {
            ws = WindowState;
            if (ws == WindowState.Minimized)
            {
                this.Hide();
            }
        }

        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            ExitApp();
        }
        private void ExitApp()
        {
            this.notifyIcon.Visible = false;
            Application.Current.Shutdown();
        }
        string savePath;
        bool isBak;
        bool isReplace;
        string timed;
        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            Start();
        }
        private void FormatConfig()
        {
            para = new Para();
            para.SavePath = "D:\\BingWallpaper";
            para.IsBak = false;
            para.IsReplace = true;
            para.Timing = "8:00:00";
            WriteConfig();
        }
        private void ReadConfig()
        {
            if (para == null)
                para = new Para();
            string str1 = "";
            if (!System.IO.File.Exists(configPath))
            {
                FormatConfig();
            }
            str1 = System.IO.File.ReadAllText(configPath);

            JObject jo;
            try
            {
                jo = JObject.Parse(str1);
                if (jo["SavePath"] == null || jo["Timing"] == null || jo["IsBak"] == null || jo["IsReplace"] == null)
                {
                    FormatConfig();
                    str1 = System.IO.File.ReadAllText(configPath, Encoding.ASCII);
                    jo = JObject.Parse(str1);
                }
                para.SavePath = jo["SavePath"].ToString();
                para.Timing = jo["Timing"].ToString();
                para.IsBak = (bool)jo["IsBak"];
                para.IsReplace = (bool)jo["IsReplace"];
            }
            catch
            {
                FormatConfig();
            }
            txtSavePath.Text = para.SavePath;
            txtTime.Text = para.Timing;
            if (para.IsBak)
                rblSave.IsChecked = true;
            else
                rblNoSave.IsChecked = true;
            if (para.IsReplace)
                rblReplace.IsChecked = true;
            else
                rblNoReplace.IsChecked = true;
        }
        private void WriteConfig()
        {
            JObject o = (JObject)JToken.FromObject(para);
            System.IO.File.WriteAllText(configPath, o.ToString());
        }

        private void Start()
        {
            if (this.btnStart.Content.ToString() == "启动")
            {
                savePath = this.txtSavePath.Text;
                if (savePath == null || savePath == "")
                {
                    MessageBox.Show("错误,保存地址不能为空");
                    return;
                }
                try
                {
                    if (!Directory.Exists(savePath))
                    {
                        Directory.CreateDirectory(savePath);
                    }
                    if (!Directory.Exists(savePath + "\\bak"))
                    {
                        Directory.CreateDirectory(savePath + "\\bak");
                    }
                }
                catch
                {
                    MessageBox.Show("错误,创建目录出错");
                    return;
                }
                para.SavePath = savePath;

                timed = this.txtTime.Text;
                DateTime t1 = DateTime.Now;
                if (timed != null && timed != "" && !DateTime.TryParse("2006-06-06 " + timed, out t1))
                {
                    MessageBox.Show("错误,定时格式错误");
                    return;
                }
                timed = t1.ToString("HH:mm:ss");
                para.Timing = timed;

                isBak = false;
                if ((bool)rblSave.IsChecked)
                    isBak = true;
                para.IsBak = isBak;

                isReplace = false;
                if ((bool)rblReplace.IsChecked)
                    isReplace = true;
                para.IsReplace = isReplace;

                WriteConfig();
                ContorlEnabled(false);
                this.btnStart.Content = "停止";
                this.labState.Visibility = Visibility.Visible;

                Thread thread1 = new Thread(Down);
                thread1.IsBackground = true;
                thread1.Start();

                dispatcherTimer.Tick += DispatcherTimer_Tick;
                dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
                dispatcherTimer.Start();
            }
            else
            {
                this.btnStart.Content = "启动";
                this.labState.Visibility = Visibility.Hidden;
                ContorlEnabled(true);
                dispatcherTimer.Stop();
            }
        }
        //ActiveDesktop ad ;
        //IActiveDesktop iad ;
        public static string GetProjectRootPath()
        {
            string path = AppDomain.CurrentDomain.BaseDirectory;
            string rootpath = path.Substring(0, path.LastIndexOf("bin"));
            return rootpath;
        }
        private void Down()
        {
            try
            {
                string url = "https://area.sinaapp.com/bingImg/";
                string currfileName = savePath + "\\bingWallpaper.jpg";
                string fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpg";
                string savefileName = savePath + "\\bak\\" + fileName;
                string projPath = GetProjectRootPath() + "\\temp\\" + fileName;

                if (SavePhotoFromUrl(savefileName, url))
                {
                    System.IO.File.Copy(savefileName, currfileName, true);
                    if (isBak)
                    {
                        //过滤一下是否有重复的文件，如果有，删除掉本次下载的。并退出
                        DirectoryInfo folder = new DirectoryInfo(savePath + "\\bak\\");
                        foreach (FileInfo file in folder.GetFiles("*.jpg"))
                        {
                            //Console.WriteLine(file.FullName);
                            if (savefileName != file.FullName && isValidFileContent(savefileName, file.FullName))
                                System.IO.File.Delete(savefileName);
                        }
                    }
                }

                System.IO.File.Copy(currfileName, projPath, true);

                labFileName.Dispatcher.Invoke(new Action(
                    delegate
                    {
                        labFileName.Content = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        imgWallpaper.Source = new BitmapImage(new Uri(projPath));
                        if (isReplace)
                        {
                            ActiveDesktop ad = new ActiveDesktop();
                            IActiveDesktop iad = ad as IActiveDesktop;
                            if (iad != null)
                            {
                                iad.SetWallpaper(currfileName, 0);
                                iad.ApplyChanges(AD_APPLY.ALL);
                                System.Runtime.InteropServices.Marshal.ReleaseComObject(ad);
                                ad = null;
                                iad = null;
                            }
                        }
                    }
                ));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        private void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            string abc = DateTime.Now.ToString("HH:mm:ss");
            if (abc == timed)
            {
                Thread thread1 = new Thread(Down);
                thread1.IsBackground = true;
                thread1.Start();
            }
        }

        private void ContorlEnabled(bool isEnabled)
        {
            this.txtSavePath.IsEnabled = isEnabled;
            this.rblNoSave.IsEnabled = isEnabled;
            this.rblSave.IsEnabled = isEnabled;
            this.txtTime.IsEnabled = isEnabled;
            this.btnSelectPath.IsEnabled = isEnabled;
            this.btnReset.IsEnabled = isEnabled;
        }
        public static bool SavePhotoFromUrl(string FileName, string Url)
        {
            bool Value = false;
            WebResponse response = null;
            Stream stream = null;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
                response = request.GetResponse();
                stream = response.GetResponseStream();
                if (!response.ContentType.ToLower().StartsWith("text/"))
                {
                    Value = SaveBinaryFile(response, FileName);
                }
            }
            catch (Exception err)
            {
                string saveerr = err.ToString();
            }
            return Value;
        }

        /// <summary>
        /// 将二进制文件保存到磁盘
        /// </summary>
        /// <param name="response"></param>
        /// <param name="FileName"></param>
        /// <returns></returns>
        private static bool SaveBinaryFile(WebResponse response, string FileName)
        {
            bool Value = true;
            byte[] buffer = new byte[1024];
            try
            {
                if (System.IO.File.Exists(FileName))
                    System.IO.File.Delete(FileName);
                Stream outStream = System.IO.File.Create(FileName);
                Stream inStream = response.GetResponseStream();

                int l;
                do
                {
                    l = inStream.Read(buffer, 0, buffer.Length);
                    if (l > 0)
                        outStream.Write(buffer, 0, l);
                }
                while (l > 0);

                outStream.Close();
                inStream.Close();
            }
            catch
            {
                Value = false;
            }
            return Value;
        }
        /// <summary>
        /// 通过文件Hash 比较两个文件内容是否相同
        /// </summary>
        /// <param name="filePath1">文件1地址</param>
        /// <param name="filePath2">文件2地址</param>
        /// <returns></returns>
        public static bool isValidFileContent(string filePath1, string filePath2)
        {
            //判断文件是否存在
            if (!System.IO.File.Exists(filePath1)) return false;
            if (!System.IO.File.Exists(filePath2)) return false;

            //创建一个哈希算法对象 
            using (HashAlgorithm hash = HashAlgorithm.Create())
            {
                using (FileStream file1 = new FileStream(filePath1, FileMode.Open), file2 = new FileStream(filePath2, FileMode.Open))
                {
                    byte[] hashByte1 = hash.ComputeHash(file1);//哈希算法根据文本得到哈希码的字节数组 
                    byte[] hashByte2 = hash.ComputeHash(file2);
                    string str1 = BitConverter.ToString(hashByte1);//将字节数组装换为字符串 
                    string str2 = BitConverter.ToString(hashByte2);
                    return (str1 == str2);//比较哈希码 
                }
            }
        }
        private void SelectPath()
        {
            System.Windows.Forms.FolderBrowserDialog openFileDialog = new System.Windows.Forms.FolderBrowserDialog();  //选择文件夹
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)//注意，此处一定要手动引入System.Window.Forms空间，否则你如果使用默认的DialogResult会发现没有OK属性
            {
                txtSavePath.Text = openFileDialog.SelectedPath;
            }
        }

        /// <summary>
        /// 开机自启创建
        /// </summary>
        /// <param name="exeName">程序名称</param>
        /// <returns></returns>
        public bool StartAutomaticallyCreate(string exeName)
        {
            try
            {
                WshShell shell = new WshShell();
                IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk");
                //设置快捷方式的目标所在的位置(源程序完整路径)
                shortcut.TargetPath = System.Windows.Forms.Application.ExecutablePath;
                //应用程序的工作目录
                //当用户没有指定一个具体的目录时，快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
                shortcut.WorkingDirectory = System.Environment.CurrentDirectory;
                //目标应用程序窗口类型(1.Normal window普通窗口,3.Maximized最大化窗口,7.Minimized最小化)
                shortcut.WindowStyle = 7;
                //快捷方式的描述
                shortcut.Description = exeName + "_Ink";
                //设置快捷键(如果有必要的话.)
                //shortcut.Hotkey = "CTRL+ALT+D";
                shortcut.Save();
                return true;
            }
            catch (Exception) { }
            return false;
        }
        /// <summary>
        /// 开机自启删除
        /// </summary>
        /// <param name="exeName">程序名称</param>
        /// <returns></returns>
        public bool StartAutomaticallyDel(string exeName)
        {
            try
            {
                System.IO.File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk");
                return true;
            }
            catch (Exception) { }
            return false;
        }

        private static bool IsStart = false;
        private void btnAutoStart_Click(object sender, RoutedEventArgs e)
        {
            if (btnAutoStart.Content.ToString() == "开机启动")
            {
                IsStart = true;
                btnAutoStart.Content = "关闭开机启动";
            }
            else
            {
                IsStart = false;
                btnAutoStart.Content = "开机启动";
            }

            if (IsStart)
                StartAutomaticallyCreate(exeName);
            else
                StartAutomaticallyDel(exeName);
        }
        private bool IsExistStart()
        {
            if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + exeName + ".lnk"))
                return true;
            else
                return false;
        }

        private void btnSelectPath_Click(object sender, RoutedEventArgs e)
        {
            SelectPath();
        }

        private void btnReset_Click(object sender, RoutedEventArgs e)
        {
            FormatConfig();
            ReadConfig();
        }


        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool SystemParametersInfo(uint uAction, uint uParam, StringBuilder lpvParam, uint init);

        /// <summary>
        /// 获取当前壁纸
        /// </summary>
        public void GetCurrWallpaper()
        {
            const uint SPI_GETDESKWALLPAPER = 0x0073;
            StringBuilder wallPaperPath = new StringBuilder(200);

            if (SystemParametersInfo(SPI_GETDESKWALLPAPER, 200, wallPaperPath, 0))
            {
                MessageBox.Show(wallPaperPath.ToString());
            }
        }

        private void btnManualDown_Click(object sender, RoutedEventArgs e)
        {
            Thread thread1 = new Thread(Down);
            thread1.IsBackground = true;
            thread1.Start();
        }
    }
}
